<!--
 * @Author: c
 * @Date: 2024-01-31 09:18:24
 * @LastEditTime: 2024-02-03 01:00:06
 * @LastEditors: c
 * @Description: 
 * @FilePath: \music-web-admin\src\views\application\music\song\components\AudioPlayer.vue
 * https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<!--
 Copyright 2024 Administrator
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
     http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

<script setup lang="ts">
import { useAudioStore } from "@/store/modules/audio";
import { durationFormat } from "@/utils";
import { Right, Switch, VideoPause, VideoPlay } from "@element-plus/icons-vue";
import { Arrayable } from "@vueuse/core";
import { storeToRefs } from "pinia";
import { onBeforeMount, onMounted, reactive, toRefs, watchEffect } from "vue";
import { useRoute, useRouter } from "vue-router";
/**
 * 仓库
 */
const store = useAudioStore();
const { lrcData } = storeToRefs(store);
/**
 * 路由对象
 */
const route = useRoute();
/**
 * 路由实例
 */
const router = useRouter();
//console.log('1-开始创建组件-setup')
/**
 * 数据部分
 */
//播放器
const audio = ref<HTMLAudioElement>();
const data = reactive<{ progress: number }>({ progress: 0 });
const isSlide = ref<boolean>(false);
//进度
const playProgress = ref<number>(0);
//当前播放时间
const currentTime = ref<number>(0);
//播放时长
const audioDuration = ref<number>(0);
//播放模式
const playMode = ref<boolean>(true);

// const props = defineProps<{
//   data: {
//     audioUrl: string;
//     album: string;
//     title: string;
//     editor: string;
//     artist: string;
//   }
// }>();

const audioUrl = computed(() => lrcData.value.audioUrl);
const emits = defineEmits<{
  (e: "updateProgress", data: number): void;
  (e: "playEnd"): void;
  (e: "play"): void;
  (e: "pause"): void;
  (e: "getCurrentTime", data: number): void;
}>();

const currentTimeStr = computed(() => durationFormat(currentTime.value * 1000));
const durationStr = computed(() => durationFormat(audioDuration.value * 1000));
const playStatus = ref<boolean>(false);

watch(
  () => playMode,
  (nv, ov) => {
    if (nv) {
    }
  }
);
watch(audioUrl, async (nv, ov) => {
  if (nv) {
    await nextTick();
    audio.value?.load();
    play();
  }
});

watch(
  () => lrcData.value.seekTime,
  (newV, oldV) => {
    console.log(audio.value, newV);
    const audioEle = audio.value as HTMLAudioElement;
    if ("fastSeek" in audio) {
      audioEle.fastSeek(newV);
    }
    audioEle.currentTime = newV;
  }
);
watch(
  () => lrcData.value.closeAudio,
  (newV, oldV) => {
    if (newV) {
      if (audio) {
        audio.value?.pause();
        audio.value?.removeAttribute("src");
        audio.value?.load();
        audio.value = undefined;
      }
      lrcData.value.album = "";
      lrcData.value.artist = "";
      lrcData.value.audioUrl = "";
      lrcData.value.editor = "";
      lrcData.value.lrcText = "";
      lrcData.value.title = "";
      lrcData.value.seekTime = 0;
    }
  }
);

// 更新进度条与当前播放时间
function updateProgress(e: Event) {
  const audioEle = e.target as HTMLAudioElement;
  const progress = audioEle.currentTime / audioEle.duration;
  playProgress.value = progress * 100;
  currentTime.value = audioEle.currentTime;

  emits("updateProgress", progress);
  // modifyProgress(progress)
  // setCurrentTime(audioEle.currentTime)
  emits("getCurrentTime", audioEle.currentTime);
  // console.log(currentTime.value);
  store.currentTime = audioEle.currentTime;
}

/**
 * 手动改变播放进度
 * @param e
 */
function changeProgress(e: Arrayable<number>) {
  isSlide.value = false;
  console.log(e);
  const progress = +e / 100;
  console.log("testtttt", progress, audioDuration.value);

  lrcData.value.seekTime = progress * audioDuration.value;
}

function immediteChangeProgress(e: Arrayable<number>) {
  console.log(e);
  isSlide.value = true;
}

function audioprocess(e: Event) {
  console.log("一个 ScriptProcessorNode 的输入缓冲区已经准备开始处理。", e);
}
function canplay(e: Event) {
  const { duration } = e.target as HTMLAudioElement;
  audioDuration.value = duration;
  console.log(
    "浏览器已经可以播放媒体，但是预测已加载的数据不足以在不暂停的情况下顺利将其播放到结尾（即预测会在播放时暂停以获取更多的缓冲区内容）",
    e
  );
}

function canplaythrough(e: Event) {
  console.log("浏览器预测已经可以在不暂停的前提下将媒体播放到结束。", e);
}

function complete(e: Event) {
  console.log("一个 OfflineAudioContext 的渲染已经中止。", e);
}
function durationchange(e: Event) {
  console.log("duration 属性发生了变化。", e);
}
function emptied(e: Event) {
  console.log(
    "媒体置空。举个例子，当一个媒体已经加载（或部分加载）的情况下话调用 load() 方法，这个事件就将被触发。",
    e
  );
}
function ended(e: Event) {
  console.log("播放到媒体的结束位置，播放停止。", e);

  // setPlayStatus('ended');

  if (playMode) {
    audio.value?.play();
  }

  emits("playEnd");
}
function loadeddata(e: Event) {
  console.log("媒体的第一帧加载完成。", e);
}
function loadedmetadata(e: Event) {
  console.log("元数据加载完成。", e);
}
function pause(e: Event) {
  console.log("暂停播放", e, audio.value?.currentTime);
  // setPlayStatus('paused');
  emits("pause");
}
function playing(e: Event) {
  console.log("因为缺少数据而暂停或延迟的状态结束，播放准备开始。", e);

  // setPlayStatus('playing');
  emits("play");
}
function ratechange(e: Event) {
  console.log("播放速度变化。", e);
}
function seeked(e: Event) {
  console.log("一次获取 操作结束。", e);
}
function seeking(e: Event) {
  console.log("一次获取 操作开始。", e);
}
function stalled(e: Event) {
  console.log("用户代理试图获取媒体数据，但数据意外地没有进入。", e);
}
function suspend(e: Event) {
  console.log("媒体加载挂起。", e);
}

function volumechange(e: Event) {
  console.log("音量变化。", e);
}
function waiting(e: Event) {
  console.log("因为暂时性缺少数据，播放暂停。", e);
}

/**
 * name
 */

const play = () => {
  playStatus.value = !playStatus.value;
  // audio.value!.currentTime! = 20;'
  console.log(audio.value?.paused);

  audio.value?.paused ? audio.value.play() : audio.value?.pause();
};

const changePlayMode = () => {
  playMode.value = !playMode.value;
};
function audioPlay() {
  console.log(
    "The Boolean paused property is now false. Either the " +
      "play() method was called or the autoplay attribute was toggled."
  );
}

onBeforeMount(() => {
  //console.log('2.组件挂载页面之前执行----onBeforeMount')
});
onMounted(() => {
  //console.log('3.-组件挂载到页面之后执行-------onMounted')
});
watchEffect(() => {});
// 使用toRefs解构
// let { } = { ...toRefs(data) }
defineExpose({
  ...toRefs(data),
});
</script>

<template>
  <div class="audio-player">
    <div class="cover-wrap">
      <img
        src=""
        alt=""
        srcset=""
      />

      <el-icon class="player-button play-btn" @click="play">
        <VideoPause v-if="playStatus" />
        <VideoPlay v-else />
      </el-icon>
    </div>
    <div class="aduio-info">
      <div v-if="lrcData.title">{{ lrcData.title }} - {{ lrcData.artist }}</div>
      <audio
        crossorigin="anonymous"
        ref="audio"
        preload="auto"
        style="display: none"
        @timeupdate="updateProgress"
        @play="audioPlay"
        @pause="pause"
        @playing="playing"
        @audioprocess="audioprocess"
        @canplay="canplay"
        @canplaythrough="canplaythrough"
        @complete="complete"
        @durationchange="durationchange"
        @emptied="emptied"
        @ended="ended"
        @loadeddata="loadeddata"
        @loadedmetadata="loadedmetadata"
        @ratechange="ratechange"
        @seeked="seeked"
        @seeking="seeking"
        @stalled="stalled"
        @suspend="suspend"
        @volumechange="volumechange"
        @waiting="waiting"
      >
        <!-- <source src="http://127.0.0.1:9000/public/admin/%E6%AF%9B%E4%B8%8D%E6%98%93%20-%20%E5%80%9F.flac"
          type="audio/mpeg" /> -->
        <source :src="audioUrl" type="audio/flac" />
        <source :src="audioUrl" type="audio/ogg" />
        <p>
          Your browser doesn't support HTML5 audio. Here is a
          <a
            href="https://m801.music.126.net/20230415223133/e06b385afb98be9b6e9c598619daae3e/jdyyaac/0e58/070f/0409/92b38a8d6c0ef9c5d6ee3cd3fe0ba0f4.m4a"
            >link to the audio</a
          >
          instead.
        </p>
      </audio>
      <div class="playing-progress-wrap">
        <ElSlider
          :show-tooltip="false"
          v-model="playProgress"
          class="playing-progress"
          size="small"
          @change="changeProgress"
          @input="immediteChangeProgress"
        />

        <div class="duration">
          <span>{{ currentTimeStr }}</span
          >/
          <span>{{ durationStr }}</span>
        </div>
        <Volume></Volume>
        <el-icon @click.prevent="changePlayMode">
          <Switch v-if="playMode" />
          <Right v-else />
        </el-icon>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.audio-player {
  position: relative;
  display: flex;
  column-gap: 20px;
  height: 100px;

  .cover-wrap {
    position: relative;
    flex-basis: 100px;
    height: 100%;

    .player-button {
      position: absolute;
      cursor: pointer;
      border-radius: 50%;
      opacity: 0.8;
      // text-shadow: 0 1px 1px rgba(0, 0, 0, .2);
      // box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
      // background: rgba(0, 0, 0, .2);
      transition: all 0.1s ease;
    }

    .play-btn {
      right: 50%;
      // border: 2px solid #fff;
      bottom: 50%;
      width: 26px;
      height: 26px;
      margin: 0 -15px -15px 0;
      font-size: 40px;
      color: #fff;
    }
  }

  .aduio-info {
    position: relative;
    flex-grow: 1;

    .playing-progress-wrap {
      position: absolute;
      bottom: 0;
      display: flex;
      flex-direction: row;
      column-gap: 10px;
      align-items: center;
      width: 100%;

      .playing-progress {
        height: 2px;

        :deep(.el-slider__runway) {
          height: 2px;
          background-color: #dadee5;
        }

        :deep(.el-slider__bar) {
          height: 2px;
          background-color: #918a8a;
        }

        :deep(.el-slider__button) {
          width: 10px;
          height: 10px;
          margin-bottom: 4px;
          background-color: #918a8a;
          border: none;
        }
      }

      .duration {
        display: flex;
        align-items: center;
      }
    }
  }
}
</style>
